home *** CD-ROM | disk | FTP | other *** search
/ SunSoft Catalyst CDWARE 1996 May to August / Catalyst CDWARE 1996 May to August.iso / .products / .bin / httpd / src / http_ipc.c < prev    next >
C/C++ Source or Header  |  1995-05-18  |  6KB  |  285 lines

  1. /*
  2.  * http_ipc.c                                                            
  3.  *    Handles the file descriptor passing.  Should work under BSD and    
  4.  *   SYSV.                                                               
  5.  *
  6.  * All code contained herein is covered by the Copyright as distributed
  7.  * in the README file in the main directory of the distribution of 
  8.  * NCSA HTTPD.
  9.  *
  10.  * Based (with modifications) on code by W. Richard Stevens, 
  11.  *    in _Advanced Programming in the UNIX Environment_
  12.  *                                                                       
  13.  * 03-06-95  blong
  14.  *    Added #ifdefs to handle not using this at all for machines like 
  15.  *     Linux.
  16.  *
  17.  * 04-17-95  blong
  18.  *    Added NEED_SPIPE with s_pipe from Stevens _Unix Network Programming_
  19.  *     for SVR3.2 systems without socketpair.
  20.  */
  21.  
  22. #ifndef NO_PASS
  23.  
  24. #include "httpd.h"
  25.  
  26. #include <sys/types.h>
  27. #if defined(FD_BSD)
  28. #include <sys/uio.h>
  29. #include <errno.h>
  30. #include <stddef.h>
  31. #elif defined(FD_SYSV)
  32. #ifdef NEED_SPIPE
  33. #define SPX_DEVICE    "/dev/spx"
  34. #include <sys/stream.h>
  35. #endif
  36. #include <stropts.h>
  37. #endif
  38. #include "new.h"
  39.  
  40. #ifdef FD_SYSV
  41.  
  42. int pass_fd(int clifd, int fd) {
  43.     char buf[2];
  44.  
  45.     buf[0] = 0;
  46.     if (fd < 0) {
  47.     buf[1] = -fd;
  48.     if (buf[1] == 0)
  49.         buf[1] = 1;
  50.     } else {
  51.     buf[1] = 0;
  52.     }
  53.  
  54.     if (write(clifd, buf, 2) != 2) {
  55.     fprintf(stderr,"pass_fd: write failed\n");
  56.     perror("pass_fd");
  57.     return -1;
  58.     }
  59.     if (fd >= 0)
  60.     if (ioctl(clifd, I_SENDFD, fd) < 0) {
  61.         fprintf(stderr,"pass_fd: ioctl failed\n");
  62.         perror("ioctl");
  63.         return -1;
  64.     }
  65.     return 0;
  66.  
  67. int recv_fd(int servfd) {
  68.     int  newfd, nread, flag, status;
  69.     char  *ptr, buf[IOBUFSIZE];
  70.     struct strbuf dat;
  71.     struct strrecvfd recvfd;
  72.  
  73.     status = -1;
  74.     for ( ; ; ) {
  75.     dat.buf = buf;
  76.     dat.maxlen = IOBUFSIZE;
  77.     flag = 0;
  78.     if (getmsg(servfd, NULL, &dat, &flag) < 0) {
  79.         fprintf(stderr,"httpd:getmsg error recv_fd\n");
  80.         perror("getmsg");
  81.         exit(1);
  82.     }
  83.     nread = dat.len;
  84.     if (nread == 0) {
  85.         fprintf(stderr,"httpd: connection closed by server\n");
  86.         exit(1);
  87.     }
  88.     
  89.     for (ptr = buf; ptr < &buf[nread]; ) {
  90.         if (*ptr++ == 0) {
  91.         if (ptr != &buf[nread-1]) {
  92.             fprintf(stderr,"httpd: message format error recv_fd\n");
  93.             perror("recv_fd");
  94.             exit(1);
  95.         }
  96.         status = *ptr & 255;
  97.         if (status == 0) {
  98.             if (ioctl(servfd, I_RECVFD, &recvfd) < 0)
  99.             return -1;
  100.             newfd = recvfd.fd;
  101.         } else 
  102.             newfd = -status;
  103.         nread -= 2;
  104.         }
  105.     }
  106.     if (status >= 0)
  107.         return (newfd);
  108.     }
  109.  
  110. #ifdef NEED_SPIPE
  111.  
  112. int s_pipe(int fd[2]) {
  113.   struct strfdinsert ins;
  114.   queue_t  *pointer;
  115.  
  116.   /*
  117.    * First open the stream clone device "/dev/spx" twice,
  118.    * obtaining the two file descriptors.
  119.    */
  120.  
  121.   if ((fd[0] = open(SPX_DEVICE, O_RDWR)) < 0) 
  122.     return -1;
  123.   if ((fd[1] = open(SPX_DEVICE, O_RDWR)) < 0)
  124.     return -1;
  125.  
  126.   /* 
  127.    * Now link these two streams together with an I_FDINSERT ioctl
  128.    */
  129.  
  130.   ins.ctlbuf.buf = (char *) &pointer;
  131.   ins.ctlbuf.maxlen = sizeof(queue_t *);
  132.   ins.ctlbuf.len = sizeof(queue_t *);
  133.  
  134.   ins.databuf.buf = (char *) 0;
  135.   ins.databuf.len = -1;
  136.   ins.databuf.maxlen = 0;
  137.  
  138.   ins.fildes = fd[1];
  139.   ins.flags = 0;
  140.   ins.offset = 0;
  141.  
  142.   if (ioctl(fd[0], I_FDINSERT, (char *) &ins) < 0) {
  143.     close(fd[0]);
  144.     close(fd[1]);
  145.     return -1;
  146.   }
  147.  
  148.   return 0;
  149.  
  150. }
  151.  
  152. #endif /* NEED_SPIPE */
  153.  
  154. #endif /* FD_SYSV */
  155.  
  156. #ifdef FD_BSD
  157.  
  158. #ifdef FD_BSDRENO
  159. static struct cmsghdr *cmptr = NULL;
  160. #define CONTROLLEN (sizeof(struct cmsghdr) + sizeof(int))
  161. #endif
  162.  
  163. int pass_fd(int clifd, int fd) {
  164.   struct iovec iov[1];
  165.   struct msghdr msg;
  166.   char  buf[2];
  167.  
  168.   iov[0].iov_base = buf;
  169.   iov[0].iov_len = 2;
  170.   msg.msg_iov = iov;
  171.   msg.msg_iovlen = 1;
  172.   msg.msg_name = NULL;
  173.   msg.msg_namelen = 0;
  174.   if (fd < 0) {
  175. #ifdef FD_BSDRENO
  176.     msg.msg_control = NULL;
  177.     msg.msg_controllen = 0;
  178. #else
  179.     msg.msg_accrights = NULL;
  180.     msg.msg_accrightslen = 0;
  181. #endif
  182.     buf[1] = -fd;
  183.     if (buf[1] == 0)
  184.       buf[1] = 1;
  185.   } else {
  186. #ifdef FD_BSDRENO
  187.     if (cmptr == NULL && (cmptr = malloc(CONTROLLEN)) == NULL)
  188.       return -1;
  189.     cmptr->cmsg_level = SOL_SOCKET;
  190.     cmptr->cmsg_type = SCM_RIGHTS;
  191.     cmptr->cmsg_len = CONTROLLEN;
  192.     msg.msg_control = (caddr_t) cmptr;
  193.     msg.msg_controllen = CONTROLLEN;
  194.     *(int *)CMSG_DATA(cmptr) = fd;
  195. #else
  196.     msg.msg_accrights = (caddr_t) &fd;
  197.     msg.msg_accrightslen = sizeof(int);
  198. #endif
  199.     buf[1] = 0;
  200.   }
  201.   buf[0] = 0;
  202.  
  203. /*  if (write(clifd, buf, 2) != 2)
  204.    return -1; */
  205.  
  206.   if (sendmsg(clifd, &msg, 0) != 2)
  207.     return -1;
  208.   
  209.   return 0;
  210. }
  211.  
  212.  
  213. int recv_fd(int servfd) {
  214.   int  nread, status;
  215.   int newfd = -1;
  216.   char *ptr, buf[IOBUFSIZE];
  217.   struct iovec  iov[1];
  218.   struct msghdr  msg;
  219.   
  220.   status = -1;
  221.   for ( ; ; ) {
  222.     iov[0].iov_base = buf;
  223.     iov[0].iov_len = sizeof(buf);
  224.     msg.msg_iov = iov;
  225.     msg.msg_iovlen = 1;
  226.     msg.msg_name = NULL;
  227.     msg.msg_namelen = 0;
  228. #ifdef FD_BSDRENO
  229.     if (cmptr == NULL && (cmptr = malloc(CONTROLLEN)) == NULL)
  230.       return -1;
  231.     msg.msg_control = (caddr_t) cmptr;
  232.     msg.msg_controllen = CONTROLLEN;
  233. #else
  234.     msg.msg_accrights = (caddr_t) &newfd;
  235.     msg.msg_accrightslen = sizeof(int);
  236. #endif
  237.     
  238.     if ((nread = recvmsg(servfd, &msg, 0)) < 0) {
  239.       fprintf(stderr,"httpd: recvmsg error");
  240.       perror("recvmsg");
  241.       exit(1);
  242.     } else if (nread == 0) {
  243.       fprintf(stderr, "httpd: connection closed by server");
  244.       exit(1);
  245.     }
  246.     
  247.     for (ptr = buf; ptr < &buf[nread]; ) {
  248.       if (*ptr++ == 0) {
  249.     if (ptr != &buf[nread-1]) {
  250.       fprintf(stderr, "httpd:message format error");
  251.       exit(1);
  252.     }
  253.     status = *ptr & 255;
  254.     if (status == 0) {
  255. #ifdef FD_BSDRENO
  256.       if (msg.msg_controllen != CONTROLLEN) 
  257. #else
  258.         if (msg.msg_accrightslen != sizeof(int)) 
  259. #endif    
  260.           {
  261.         fprintf(stderr, "httpd: status = 0 but no fd");
  262.         exit(1);
  263.           }
  264. #ifdef FD_BSDRENO
  265.       newfd = *(int *)CMSG_DATA(cmptr);
  266. #endif
  267.     } else 
  268.       newfd = -status;
  269.       nread -= 2;
  270.       }
  271.     }
  272.     if (nread > 0)
  273.       return -1;
  274.     if (status >= 0)
  275.       return newfd;
  276.   }
  277. }
  278.   
  279.  
  280. #endif
  281.  
  282. #endif 
  283.